
/* GCSx
** IMGSELECT.H
**
** Image/tile/sprite selection toolbar
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#ifndef __GCSx_IMGSELECT_H_
#define __GCSx_IMGSELECT_H_

// One image
// Tile/Image set is specifically not included
class Image {
public:
    Uint16 index;
    Uint16 color; // 4 bits each RGB (see gcsx_layer.h)
    Uint8 alpha; // 4 bits (see gcsx_layer.h)
    Uint8 effects; // See enum
    
    enum {
        EFFECTS_FLIP   = 0x01,
        EFFECTS_MIRROR = 0x02,
        EFFECTS_ROTATE = 0x04,
        
        // (see gcsx_layer.h)
        COLOR_BITDEPTH = 4,
        COLOR_DEFAULT  = 0xFFF,
        ALPHA_BITDEPTH = 4,
        ALPHA_DEFAULT  = 0xF,
    };
    
    Image();
};

// One or more images form a pattern
// Tile/Image set is specifically not included
class Pattern {
public:
    struct PatternEntry {
        Image image;
        int x;
        int y;
    };
    
    std::vector<PatternEntry> images;
    int count;
    int width;
    int height;

    Pattern();
};

// A set of images shown by ImageSelect
class ShownImages {
public:
    enum {
        // How many recent patterns we remember
        PATTERN_RECENT_MAX = 32,
    };

    // Top image for strip
    Image strip;
    
    // Recently selected images/patterns
    Pattern recent[PATTERN_RECENT_MAX];
    
    ShownImages(const class TileSetEdit* tiles);
};

class ImageSelect : public Window {
private:
    class FrameWindow* myFrame;

    enum {
        // Number of images to show in strip, default
        IMAGE_COUNT = 7,
        IMAGE_ACROSS = 3,
        // Maximum size of images (scaled if needed)
        IMAGE_MAX_SIZE = 64,
        // Minimum size of images (because also used for button height)
        IMAGE_MIN_SIZE = 16,
        // Separation between images AND bordering images- used to denote selection
        // Also separation between images and related buttons
        // Also border on top/bottom of rows
        IMAGE_SEPARATION = 4,
        // Bevel size on images
        IMAGE_BEVEL = 1,
        // Gutter between row types (this is instead of any other separation)
        IMAGE_GUTTER = 4,
        
        // Selected/drag types
        SELECTED_STRIP = 1, // an item on the main strip is selected
        SELECTED_NONE = 2, // the "none" item is selected
        SELECTED_RECENT = 3, // a "recent" item is selected
        
        DRAG_NONE = 0,
        DRAG_STRIP_PREV = 5,
        DRAG_RECENT_MORE = 6,
        DRAG_STRIP_NEXT = 7,
        DRAG_STRIP_MORE = 8,
    };
    
    // Where the images are coming from
    class TileSetEdit* tileset; // Not const- markLock/Unlock is not const
    const class ColorStore* colors;
    int useAlpha;
    int numImages;
    int imageWidth; // Actual
    int imageHeight;
    int zoomWidth; // Displayed size
    int zoomHeight;
    int paddedWidth; // Size of area zoomed tile is shown in
    int paddedHeight;
    
    int showVertical; // Vertically align?
    int numImagesShownCount; // Number along main axis
    int numImagesShownAcross; // Number across axis
    int numPatternsShown;
    int blankTileCenter;
    
    // Have "none" and "recent" items?
    int extendedFeatures;
    
    // Currently shown images    
    ShownImages shown;
    
    // Remembers the most recently shown items on a
    // tileset-by-tileset basis
    static std::map<const void*,ShownImages>* shownBank;
    
    // Selected
    int selectedType;
    int selectedIndex; // Not valid for 'none' item
    int dragType;
    int prevDrag;
    
    // Buttons
    static const std::string wtButtonPrevV;
    static const std::string wtButtonNextV;
    static const std::string wtButtonPrevH;
    static const std::string wtButtonNextH;
    static const std::string wtButtonExpand;
    int buttonHeight;
    static int buttonWidth;
    
    void dragLocation(int mX, int mY, int& type, int& index) const;
    
    // Helpers for display; return suggested advancement height
    int drawButton(SDL_Surface* destSurface, int baseX, int baseY, int offsX, int offsY, const std::string& wText, int pressed) const;
    int drawBlankImage(SDL_Surface* destSurface, int baseX, int baseY, int offsX, int offsY, int selected) const;
    // pattern OR image, NULL = none
    int drawPattern(SDL_Surface* destSurface, int baseX, int baseY, int offsX, int offsY, int selected, Image* image, Pattern* pattern) const;

    void saveDef();

public:
    ImageSelect(TileSetEdit* tiles, const class ColorStore* cStorage, int useExtendedFeatures = 1) throw_File;
    ~ImageSelect();
    
    // Creates a FrameWindow and returns, does not add self to desktop (use ->show() to do that)
    class FrameWindow* createWindowed();
    
    // Changes settings
    void changeSet(class TileSetEdit* tiles, int oldDeleted = 0) throw_File;
    void allowAlpha(int newUseAlpha);
    
    // Alert that color has changed
    void colorRefresh();
    
    // next/prev on main strip
    void nextImage();
    void prevImage();
    
    // select specific image centered on main strip
    void selectImage(int tile);
    
    // get data/fx/ext for currently selected item
    void getDataExt(Uint32& data, Uint32& ext, Uint32& fx) const;

    int event(int hasFocus, const SDL_Event* event);
    void resize(int newWidth, int newHeight, int newViewWidth = -1, int newViewHeight = -1, int fromParent = 0);
    void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
    const char* tooltip(int xPos, int yPos) const;
    WindowType windowType() const;
    
    static void destroyGlobals();
};

#endif

